home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / libgutil / texture.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  12KB  |  752 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *    texture -
  19.  *        Support for software texture maps.
  20.  *
  21.  *                Paul Haeberli - 1988
  22.  */
  23. #include "values.h"
  24. #include "texture.h"
  25. #include "resource.h"
  26. #include "port.h"
  27.  
  28. static init_noise3();
  29. static normalize();
  30. float frand();
  31. float fnoise3();
  32.  
  33. #define DEGTORAD(x)    (((x)*M_PI)/180.0)
  34.  
  35. /*
  36.  *    Utility Functions 
  37.  *
  38.  */ 
  39. float onewrap(v)
  40. float v;
  41. {
  42.     if(v >= 0.0)
  43.     return (v - ((int)v));
  44.     v = -v;
  45.     return 1.0-(v - ((int)v));
  46. }
  47.  
  48. float ease(x)
  49. float x;
  50. {
  51.     if(x<0.0)
  52.     return 0.0;
  53.     if(x>1.0)
  54.     return 1.0;
  55.     return (sin(DEGTORAD(180.0*(x-0.5)))+1.0)/2.0;
  56. }
  57.  
  58. vcubewrap(v,vw)
  59. vect *v, *vw;
  60. {
  61.     vw->x = onewrap(v->x);
  62.     vw->y = onewrap(v->y);
  63.     vw->z = onewrap(v->z);
  64. }
  65.  
  66. vforceunit(v)
  67. vect *v;
  68. {
  69.     if(v->x<0.0)
  70.     v->x = 0.0;
  71.     if(v->y<0.0)
  72.     v->y = 0.0;
  73.     if(v->z<0.0)
  74.     v->z = 0.0;
  75.     if(v->w<0.0)
  76.     v->w = 0.0;
  77.     if(v->x>1.0)
  78.     v->x = 1.0;
  79.     if(v->y>1.0)
  80.     v->y = 1.0;
  81.     if(v->z>1.0)
  82.     v->z = 1.0;
  83.     if(v->w>1.0)
  84.     v->w = 1.0;
  85. }
  86.  
  87. addnormals(a,b,c)
  88. vect *a, *b, *c;
  89. {
  90.     vadd(a,b,c);
  91.     vnormal(c);
  92. }
  93.  
  94. /*
  95.  *     Texture mapping support 
  96.  *
  97.  */
  98. TEXTURE *tmalloc(xsize,ysize,zsize,bpp)
  99. int xsize, ysize, zsize, bpp;
  100. {
  101.     TEXTURE *tm;
  102.     unsigned char *buf;
  103.     int y;
  104.  
  105.     tm = (TEXTURE *)mymalloc(sizeof(TEXTURE));
  106.     tm->xsize = xsize;
  107.     tm->ysize = ysize;
  108.     tm->zsize = zsize;
  109.     tm->bpp = bpp;
  110.     tm->data = (unsigned char **)mymalloc(sizeof(char *)*ysize);
  111.     buf = (unsigned char *)mymalloc(tm->bpp*tm->xsize*tm->ysize*tm->zsize);
  112.     for(y=0; y<ysize; y++) {
  113.     tm->data[y] = buf;
  114.     buf += tm->bpp*tm->xsize*tm->zsize;
  115.     }
  116.     return tm;
  117. }
  118.  
  119. TEXTURE *tmopen(name)
  120. char *name;
  121. {
  122.     TEXTURE *tm;
  123.     IMAGE *image;
  124.     int y, z, bpp;
  125.     short *sbuf;
  126.  
  127.     image = iopen(name,"r");
  128.     if(!image) 
  129.     return 0;
  130.     if(BPP(image->type) == 1)
  131.     bpp = 1;
  132.     else
  133.     bpp = 2;
  134.     tm = tmalloc(image->xsize,image->ysize,image->zsize,bpp);
  135.     sbuf = (short *)malloc(image->xsize*sizeof(short));
  136.     for(y=0; y<image->ysize; y++) {
  137.     for(z=0; z<image->zsize; z++) {
  138.         getrow(image,sbuf,y,z);
  139.         copytotm(sbuf,tm,y,z);
  140.     }
  141.     }
  142.     free(sbuf);
  143.     iclose(image);
  144.     return tm;
  145. }
  146.  
  147. copytotm(rowbuf,tm,y,z)
  148. short *rowbuf;
  149. TEXTURE *tm;
  150. int y, z;
  151. {
  152.     int n, zsize;
  153.     unsigned char *cdata;
  154.     unsigned short *sdata;
  155.  
  156.     zsize = tm->zsize;
  157.     n = tm->xsize;
  158.     if(tm->bpp == 1) {
  159.     cdata = tm->data[y]+z;
  160.     while(n--) {
  161.         *cdata = *rowbuf++;
  162.         cdata += zsize;
  163.     }
  164.     } else {
  165.     sdata = ((unsigned short *)tm->data[y])+z;
  166.     while(n--) {
  167.         *sdata = *rowbuf++;
  168.         sdata += zsize;
  169.     }
  170.     }
  171. }
  172.  
  173. tmfree(tm)
  174. TEXTURE *tm;
  175. {
  176.     if(tm) {
  177.     free(tm->data[0]);
  178.     free(tm->data);
  179.     free(tm);
  180.     }
  181. }
  182.  
  183. tmclose(tm)
  184. TEXTURE *tm;
  185. {
  186.     tmfree(tm);
  187. }
  188.  
  189. tmsample(tm,v,c)
  190. TEXTURE *tm;
  191. vect *v, *c;
  192. {
  193.     int xpos;
  194.     int ypos;
  195.  
  196.     xpos = onewrap(v->x)*(tm->xsize);
  197.     if(xpos == tm->xsize)
  198.     xpos = tm->xsize-1;
  199.     ypos = onewrap(v->y)*(tm->ysize);
  200.     if(ypos == tm->ysize)
  201.     ypos = tm->ysize-1;
  202.     imgsample(tm,xpos,ypos,c);
  203. }
  204.  
  205. imgsample(tm,xpos,ypos,c)
  206. TEXTURE *tm;
  207. int xpos, ypos;
  208. vect *c;
  209. {
  210.     int zsize;
  211.     unsigned char *cdata;
  212.     unsigned short *sdata;
  213.     float val;
  214.  
  215.     zsize = tm->zsize;
  216.     if(tm->bpp == 1) {
  217.     cdata = tm->data[ypos]+xpos*zsize;
  218.     switch(tm->zsize) {
  219.         case 1:
  220.         c->x = c->y = c->z = *cdata/255.0;
  221.         break;
  222.         case 2:
  223.         c->x = *cdata++/255.0;
  224.         c->y = c->z = *cdata/255.0;
  225.         break;
  226.         case 3:
  227.         c->x = *cdata++/255.0;
  228.         c->y = *cdata++/255.0;
  229.         c->z = *cdata/255.0;
  230.         break;
  231.         case 4:
  232.         c->x = *cdata++/255.0;
  233.         c->y = *cdata++/255.0;
  234.         c->z = *cdata++/255.0;
  235.         c->w = *cdata/255.0;
  236.         break;
  237.     }
  238.     } else {
  239.     sdata = ((unsigned short *)tm->data[ypos])+xpos*zsize;
  240.     switch(tm->zsize) {
  241.         case 1:
  242.         c->x = c->y = c->z = *sdata/255.0;
  243.         break;
  244.         case 2:
  245.         c->x = *sdata++/255.0;
  246.         c->y = c->z = *sdata/255.0;
  247.         break;
  248.         case 3:
  249.         c->x = *sdata++/255.0;
  250.         c->y = *sdata++/255.0;
  251.         c->z = *sdata/255.0;
  252.         break;
  253.         case 4:
  254.         c->x = *sdata++/255.0;
  255.         c->y = *sdata++/255.0;
  256.         c->z = *sdata++/255.0;
  257.         c->w = *sdata/255.0;
  258.         break;
  259.     }
  260.     }
  261. }
  262.  
  263. #define XBIG    0
  264. #define YBIG    1
  265. #define ZBIG    2
  266.  
  267. static float deltax[6] = {
  268.     0.0, 1.0, 2.0,
  269.     0.0, 1.0, 2.0,
  270. };
  271.  
  272. static float deltay[6] = {
  273.     0.0, 0.0, 0.0,
  274.     1.0, 1.0, 1.0,
  275. };
  276.  
  277. envsample(tm,v,c)
  278. TEXTURE *tm;
  279. vect *v, *c;
  280. {
  281.     vect t;
  282.     int xpos, ypos;
  283.  
  284.     vecttoenv(v,&t);
  285.     xpos = t.x*tm->xsize;
  286.     if(xpos >= tm->xsize)
  287.     xpos = tm->xsize-1;
  288.     ypos = t.y*tm->ysize;
  289.     if(ypos >= tm->ysize)
  290.     ypos = tm->ysize-1;
  291.     imgsample(tm,xpos,ypos,c);
  292. }
  293.  
  294. vecttoenv(v,e)
  295. vect *v, *e;
  296. {
  297.     int code, seg;
  298.     float tx, ty;
  299.     float xabs, yabs, zabs;
  300.  
  301.     xabs = 2.001*ABS(v->x);
  302.     yabs = 2.001*ABS(v->y);
  303.     zabs = 2.001*ABS(v->z);
  304.     if(xabs>yabs) {
  305.     if(xabs>zabs) 
  306.         code = XBIG;
  307.     else 
  308.         code = ZBIG;
  309.     } else {
  310.     if(yabs>zabs) 
  311.         code = YBIG;
  312.     else 
  313.         code = ZBIG;
  314.     }
  315.     switch(code) {
  316.     case XBIG:
  317.         if(xabs<0.001) {
  318.         printf("vecttoenv\n");
  319.         vprint(v);
  320.         }
  321.         tx = 0.5+(v->y/xabs);
  322.         ty = 0.5+(v->z/xabs);
  323.         if(v->x>0.0) 
  324.         seg = 3;
  325.         else 
  326.         seg = 0;
  327.         break;
  328.     case YBIG:
  329.         if(yabs<0.001) {
  330.         printf("vecttoenv\n");
  331.         vprint(v);
  332.         }
  333.         tx = 0.5+(v->z/yabs);
  334.         ty = 0.5+(v->x/yabs);
  335.         if(v->y>0.0) 
  336.         seg = 4;
  337.         else 
  338.         seg = 1;
  339.         break;
  340.     case ZBIG:
  341.         if(zabs<0.001) {
  342.         printf("vecttoenv\n");
  343.         vprint(v);
  344.         }
  345.         tx = 0.5+(v->x/zabs);
  346.         ty = 0.5+(v->y/zabs);
  347.         if(v->z>0.0) 
  348.         seg = 5;
  349.         else 
  350.         seg = 2;
  351.         break;
  352.     }
  353.     tx += deltax[seg];
  354.     ty += deltay[seg];
  355.     e->x = tx/3.0;
  356.     e->y = ty/2.0;
  357.     e->z = 0.0;
  358. }
  359.  
  360. envtovect(e,v)
  361. vect *e, *v;
  362. {
  363.     int seg;
  364.     float tx, ty;
  365.  
  366.     tx = 3.0*e->x;
  367.     ty = 2.0*e->y;
  368.     seg = 0;
  369.     if(ty>1.0) {
  370.     seg = 3;
  371.     ty -= 1.0;
  372.     } else
  373.     seg = 0;
  374.     if(tx>2.0) {
  375.     seg += 2;
  376.     tx -= 2.0;
  377.     } else if(tx>1.0) {
  378.     seg += 1;
  379.     tx -= 1.0;
  380.     }
  381.     tx -= 0.5;
  382.     ty -= 0.5;
  383.     switch(seg) {
  384.     case 0:
  385.         v->x = -0.5;
  386.         v->y = tx;
  387.         v->z = ty;
  388.         break;
  389.     case 1:
  390.         v->y = -0.5;
  391.         v->z = tx;
  392.         v->x = ty;
  393.         break;
  394.     case 2:
  395.         v->z = -0.5;
  396.         v->x = tx;
  397.         v->y = ty;
  398.         break;
  399.     case 3:
  400.         v->x = 0.5;
  401.         v->y = tx;
  402.         v->z = ty;
  403.         break;
  404.     case 4:
  405.         v->y = 0.5;
  406.         v->z = tx;
  407.         v->x = ty;
  408.         break;
  409.     case 5:
  410.         v->z = 0.5;
  411.         v->x = tx;
  412.         v->y = ty;
  413.         break;
  414.     }
  415.     vnormal(v);
  416. }
  417.  
  418. spheretovect(s,v)
  419. vect *s, *v;
  420. {
  421.     float mag, mag2, d;
  422.     
  423.     mag2 = s->x*s->x+s->y*s->y;
  424.     if(mag2>=1.0) {
  425.     v->x = 0.0;
  426.     v->y = 0.0;
  427.     v->z = 1.0;
  428.     return 0;
  429.     } else {
  430.     d = sqrt(1.0-mag2);
  431.     v->x = s->x;
  432.     v->y = s->y;
  433.     v->z = d;
  434.     return 1;
  435.     }
  436. }
  437.  
  438. /*
  439.  *    Signals 
  440.  *
  441.  */
  442. float wave(pos)
  443. vect *pos;
  444. {
  445.     float dist;
  446.  
  447.     dist = sqrt(pos->x*pos->x+pos->y*pos->y+pos->z*pos->z);
  448.     dist = onewrap(dist); 
  449.     return sin(DEGTORAD(dist*360.0));
  450. }
  451.  
  452. float noisefunc(v)
  453. vect *v;
  454. {
  455.     float x, y, z;
  456.  
  457.     x = v->x;
  458.     y = v->y;
  459.     z = v->z;
  460.     return fnoise3(x,y,z);
  461. }
  462.  
  463. #define NWAVES    10
  464.  
  465. float ocean(pos)
  466. vect *pos;
  467. {
  468.     static int firsted;
  469.     static vect origin[NWAVES];
  470.     int i;
  471.     float sum;
  472.     vect p;
  473.  
  474.     if(!firsted) {
  475.     for(i=0; i<NWAVES; i++) {
  476.         origin[i].x = 30.0*(frand()-0.5);
  477.         origin[i].y = 30.0*(frand()-0.5);
  478.         origin[i].z  = 0.0;
  479.     }
  480.     firsted++;
  481.     }
  482.     sum = 0.0;
  483.     for(i=0; i<NWAVES; i++) {
  484.     vadd(pos,origin+i,&p);
  485.     sum += wave(&p);
  486.     }
  487.     return sum/NWAVES;
  488. }
  489.  
  490. float turbulence(v,n)
  491. vect *v;
  492. int n;
  493. {
  494.     int i;
  495.     float total, val, mag, mult;
  496.     vect p;
  497.  
  498.     p = *v;
  499.     vscale(&p,4.0);
  500.     total = 0;
  501.     mag = 0.0;
  502.     mult = 1.0;
  503.     for(i=0; i<n; i++) {
  504.     val = mult*noisefunc(&p);
  505.     total += ABS(val);
  506.     mag += mult;
  507.     mult /= 2.0;
  508.     vscale(&p,2.0);
  509.     }
  510.     total /= mag;
  511.     return total;
  512. }
  513.  
  514.  
  515. /*
  516.  *     Some textures 
  517.  *
  518.  */
  519. texchecks(v,c)
  520. vect *v, *c;
  521. {
  522.     vect vw;
  523.     int val;
  524.     
  525.     vcubewrap(v,&vw);
  526.     val = 1;
  527.     if(vw.x>0.5)
  528.     val = -val;
  529.     if(vw.y>0.5)
  530.     val = -val;
  531.     if(vw.z>0.5)
  532.     val = -val;
  533.     if(val >0) {
  534.     c->x = 1.0;
  535.     c->y = 1.0;
  536.     c->z = 1.0;
  537.     } else {
  538.     c->x = 0.0;
  539.     c->y = 0.0;
  540.     c->z = 0.0;
  541.     }
  542. }
  543.  
  544. texrampx(v,c)
  545. vect *v, *c;
  546. {
  547.     float xpos;
  548.     int val;
  549.     
  550.     xpos = onewrap(v->x);
  551.     c->x = xpos;
  552.     c->y = xpos;
  553.     c->z = xpos;
  554. }
  555.  
  556. /*
  557.  *    noise -
  558.  *        Fixed point implementation of Noise, in the C language
  559.  *    from Ken Perlin.
  560.  *
  561.  */
  562. #define SIZE    64
  563.  
  564. #define NP    (12)
  565. #define N    (1<<NP)
  566.  
  567. #define BP    (8)
  568. #define B    (1<<BP)
  569.  
  570. static s_curve[N];
  571. static p[B+B+2];
  572. static g[B+B+2][3];
  573.  
  574. #define setup(x,b0,b1,r0,r1,s)             \
  575.     x = x + (1<<(NP+BP));            \
  576.     b0 = (x>>NP)&(B-1);            \
  577.     b1 = (b0+1) &(B-1);            \
  578.     r0 = x & (N-1);                \
  579.     r1 = r0 - N;                \
  580.     s = s_curve[r0];            
  581.     
  582. #define at(b,rx,ry,rz)     (q = g[b],(rx*q[0]+ry*q[1]+rz*q[2])>>NP)
  583.  
  584. #define lerp(t,a,b)    (a+((t*(b-a))>>NP))
  585.  
  586. static int firsted = 0;
  587.  
  588. noise3(x,y,z)
  589. int x, y, z;
  590. {
  591.     int bx0, bx1, by0, by1, bz0, bz1;
  592.     int rx0, rx1, ry0, ry1, rz0, rz1;
  593.     int b00, b10, b01, b11;
  594.     int t000, t100, t010, t110;
  595.     int t001, t101, t011, t111;
  596.     int t00, t10, t01, t11;
  597.     int t0, t1;
  598.     int sx, sy, sz;
  599.     int *q;
  600.  
  601.     if(!firsted) {
  602.         init_noise3();
  603.         firsted = 1;
  604.     }
  605.  
  606.     setup(x,bx0,bx1,rx0,rx1,sx);
  607.     setup(y,by0,by1,ry0,ry1,sy);
  608.     setup(z,bz0,bz1,rz0,rz1,sz);
  609.  
  610.     b00 = p[p[bx0]+by0];
  611.     b10 = p[p[bx1]+by0];
  612.     b01 = p[p[bx0]+by1];
  613.     b11 = p[p[bx1]+by1];
  614.  
  615.     t000 = at(b00+bz0,rx0,ry0,rz0);
  616.     t100 = at(b10+bz0,rx1,ry0,rz0);
  617.     t010 = at(b01+bz0,rx0,ry1,rz0);
  618.     t110 = at(b11+bz0,rx1,ry1,rz0);
  619.     t001 = at(b00+bz1,rx0,ry0,rz1);
  620.     t101 = at(b10+bz1,rx1,ry0,rz1);
  621.     t011 = at(b01+bz1,rx0,ry1,rz1);
  622.     t111 = at(b11+bz1,rx1,ry1,rz1);
  623.  
  624.     t00 = lerp(sx,t000,t100);
  625.     t10 = lerp(sx,t010,t110);
  626.     t01 = lerp(sx,t001,t101);
  627.     t11 = lerp(sx,t011,t111);
  628.  
  629.     t0 = lerp(sy,t00,t10);
  630.     t1 = lerp(sy,t01,t11);
  631.  
  632.     return lerp(sz,t0,t1);
  633. }
  634.  
  635. /*
  636.  *    fnoise - 
  637.  *        Return a value between -1.0 and +1.0
  638.  *
  639.  */
  640. float fnoise3(x,y,z)
  641. float x, y, z; 
  642. {
  643.     int ix, iy, iz;
  644.  
  645.     ix = N*x;
  646.     iy = N*y;
  647.     iz = N*z;
  648.     return noise3(ix,iy,iz)/128.0;
  649. }
  650.  
  651. static init_noise3()
  652. {
  653.     long random();
  654.     int i, j, k;
  655.     double t;
  656.  
  657.     for(i=0; i<N; i++) {
  658.         t = (double)i/N;
  659.         if(i>N/2) t = 1.0-t;
  660.         t = 4*t*t*t;
  661.         if(i>N/2) t = 1.0-t;
  662.         s_curve[i] = N*t;
  663.     }
  664.     for(i=0; i<B; i++) {
  665.             p[i] = i;
  666.         for(j=0; j<3; j++) {
  667.             g[i][j] = (random()%(B+B))-B;
  668.         }
  669.         normalize(g[i]);
  670.     }
  671.     while(--i) {
  672.         k = p[i];
  673.         p[i] = p[j=random()%B];
  674.         p[j] = k;
  675.     }
  676.     for(i=0; i<B+2; i++) {
  677.         p[B+i] = p[i];
  678.         for(j=0; j<3; j++)
  679.             g[B+i][j] = g[i][j];
  680.     }
  681. }
  682.  
  683. static normalize(v)
  684. int v[3];
  685. {
  686.     double s;
  687.  
  688.     s = sqrt((double)(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]));
  689.     v[0] = (B*v[0])/s;
  690.     v[1] = (B*v[1])/s;
  691.     v[2] = (B*v[2])/s;
  692. }
  693.  
  694. tmavg(tm,avg)
  695. TEXTURE *tm;
  696. vect *avg;
  697. {
  698.     int xsize, ysize;
  699.     int x, y;
  700.     vect c, acc;
  701.  
  702.     xsize = tm->xsize;
  703.     ysize = tm->ysize;
  704.     vzero(avg);
  705.     for(y=0; y<ysize; y++) {
  706.     vzero(&acc);
  707.     for(x=0; x<xsize; x++) {
  708.         imgsample(tm,x,y,&c);
  709.         vadd(&c,&acc,&acc);
  710.     }
  711.     vscale(&acc,1.0/xsize);
  712.     vadd(&acc,avg,avg);
  713.     }
  714.     vscale(avg,1.0/ysize);
  715. }
  716.  
  717. TEXTURE *restotm(name)
  718. char *name;
  719. {
  720.     FILE *inf;
  721.     int rasdata;
  722.     TEXTURE *ftm, *tm;
  723.  
  724.     inf = res_fopen(name,"r");
  725.     ftm = (TEXTURE *)mymalloc(sizeof(TEXTURE));
  726.     res_fread(ftm,1,sizeof(TEXTURE),inf);
  727.     tm = tmalloc(ftm->xsize,ftm->ysize,ftm->zsize,ftm->bpp);
  728.     rasdata = tm->xsize*tm->ysize*tm->zsize*tm->bpp;
  729.     res_fread(tm->data[0],1,rasdata,inf);
  730.     res_fclose(inf);
  731.     free(ftm);
  732.     return tm;
  733. }
  734.  
  735. tmtores(tm,name)
  736. TEXTURE *tm;
  737. char *name;
  738. {
  739.     FILE *outf;
  740.     int rasdata;
  741.  
  742.     outf = fopen(name,"w");
  743.     if(!outf) {
  744.     fprintf(stderr,"can't open output file %s\n",name);
  745.     exit(1);
  746.     }
  747.     fwrite(tm,1,sizeof(TEXTURE),outf);
  748.     rasdata = tm->xsize*tm->ysize*tm->zsize*tm->bpp;
  749.     fwrite(tm->data[0],1,rasdata,outf);
  750.     fclose(outf);
  751. }
  752.